#-*- coding: utf-8 -*-

#This file is part of pyLot library.
#
# pyLot is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyLot is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pyLot.  If not, see <http://www.gnu.org/licenses/>.

__author__ = u'Pierre Puiseux, Guillaume Baty'
__copyright__ = u"Copyright 2011-2012 (C) andheo, Université de Pau et des Pays de l'Adour"
__credits__ = [u'Pierre Puiseux', u'Guillaume Baty']
__license__ = "GNU Lesser General Public License"

__all__ = [
  'FILTERS',
  'GuiBoolFilter',
  'GuiEmptyFilter',
  'GuiFilter',
  'GuiNumFilter',
  'GuiPredefUnicodeFilter',
  'GuiUnicodeFilter',
  'make_filter',
  ]

import re
import fnmatch

from Qt4 import QtGui, QtCore

from pyLot.core import make_alias, Datum
from pyLot.core import evaluators, regexpr

from _pylot.qtgui.custom import DEFAULT_CUSTOM
from _pylot.qtgui.widgets.gui_typedselectors import *
from _pylot.qtgui.styles.policy import HSMALL

int_filter = Datum(u'int_filter', unicode, u'value > 0',
                   value_list=[u'value >= 0', u'value <= 0', u'value < 0',
                               u'-1 < value < 1', u'value != 0'])

unicode_filter = Datum(u'unicode_filter', unicode, u'*')

#co_glob = 

class GuiEmptyFilter(QtGui.QGroupBox):

  filterChanged = QtCore.Signal()

  def __init__(self, datum, custom=DEFAULT_CUSTOM):
    QtGui.QGroupBox.__init__(self, make_alias(datum))
    self.setCheckable(True)
    self.setFlat(True)

    self.custom = custom
    self.datum = datum

    self.layout_main = QtGui.QHBoxLayout(self)
    self.layout_main.setContentsMargins(0, 0, 0, 0)
    self.setSizePolicy(HSMALL)

    self.toggled.connect(self._emit)

  def refresh(self):
    pass

  def _emit(self, *args):
    self.filterChanged.emit()

  def match(self, value):
    return True

class GuiFilter(QtGui.QGroupBox):

  filterChanged = QtCore.Signal()

  def __init__(self, datum, selector, custom=DEFAULT_CUSTOM):
    QtGui.QGroupBox.__init__(self, make_alias(datum))

    self.custom = custom
    self.datum = datum
    self.selector = selector

    self.setCheckable(True)
    self.setFlat(True)


    self.layout_main = QtGui.QHBoxLayout(self)
    self.layout_main.setContentsMargins(0, 0, 0, 0)
    self.setSizePolicy(HSMALL)

    self.toggled.connect(self._emit)
    self.selector.valueChanged.connect(self._emit)

    self.setChecked(False)

  def refresh(self):
    pass

  def _emit(self, *args):
    # uses *args instead of "state" because on some python/PySide 
    # versions, sometimes signal sends a boolean, other times nothing !!!
    if self.isChecked():
      self.match = self._match
    else :
      self.match = self.returnTrue
    self.filterChanged.emit()


  def returnTrue(self, value):
    return True

  def _match(self, value):
    return True

class GuiBoolFilter(GuiFilter):
  def __init__(self, datum, custom=DEFAULT_CUSTOM):
    selector = GuiRadioBoolSelector(datum, custom=custom)
    GuiFilter.__init__(self, datum, selector, custom)
    self.layout_main.addWidget(selector)

  def _match(self, value):
    return value is self.selector.value()

class GuiNumFilter(GuiFilter):
  def __init__(self, datum, custom=DEFAULT_CUSTOM):
    selector = GuiUnicodeSelector(int_filter, custom=custom)
    GuiFilter.__init__(self, datum, selector, custom)
    self.layout_main.addWidget(selector)

  def _match(self, value):
    return evaluators.eval_value_expr(self.selector.value(), value)

class GuiUnicodeFilter(GuiFilter):
  def __init__(self, datum, custom=DEFAULT_CUSTOM):
    selector = GuiUnicodeSelector(unicode_filter, custom=custom)
    GuiFilter.__init__(self, datum, selector, custom)
    self.layout_main.addWidget(self.selector)

  def _match(self, value):
    filt = self.selector.value()
    if not filt :
      return True
    elif filt and not value:
      return False
    elif filt[0] == u'!' :
      return not bool(fnmatch.fnmatchcase(value, filt[1:]))
    else:
      return bool(fnmatch.fnmatchcase(value, filt))


class GuiPredefUnicodeFilter(GuiFilter):
  def __init__(self, datum, custom=DEFAULT_CUSTOM):
    selector = GuiPredefUnicodeSelector(datum, custom=custom)
    GuiFilter.__init__(self, datum, selector, custom)
    self.different = QtGui.QCheckBox(u'≠')
    self.layout_main.addWidget(self.different)
    self.layout_main.addWidget(selector)
    self.different.toggled.connect(self._emit)
    self.different.setSizePolicy(HSMALL)
    self.different.setMaximumWidth(40)

  def setValueList(self, value_list):
    self.selector.setValueList(value_list)

  def refresh(self):
    self.selector.refresh()

  def _match(self, value):
    return value == self.selector.value()

  def _doNotMatch(self, value):
    return value != self.selector.value()

  def _emit(self, *args):
    if self.isChecked() and self.different.isChecked():
      self.match = self._doNotMatch
    elif self.isChecked():
      self.match = self._match
    else :
      self.match = self.returnTrue
    self.filterChanged.emit()


FILTERS = {
  bool:GuiBoolFilter,
  unicode:GuiUnicodeFilter,
  int:GuiNumFilter,
  float:GuiNumFilter,
  }

def make_filter(datum, custom=DEFAULT_CUSTOM):
  try :
    filter_class = FILTERS[datum.nature]
  except KeyError :
    filter_class = GuiEmptyFilter

  filter_class = custom.getOption(u'filter', None, datum, filter_class)
  return filter_class(datum, custom=custom)

if __name__ == '__main__' :
  pass
